#pragma once

typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;

#pragma pack(push)
#pragma pack(1)

/* 4 bytes IP address */
union ip_address{
	uint32 ulong;
	struct{
		u_char byte1;
		u_char byte2;
		u_char byte3;
		u_char byte4;
	};
};

/* IPv4 header */
struct ip_header{
	u_char  ver_ihl;        // Version (4 bits) + Internet header length (4 bits)
	u_char  tos;            // Type of service 
	u_short tlen;           // Total length 
	u_short identification; // Identification
	u_short flags_fo;       // Flags (3 bits) + Fragment offset (13 bits)
	u_char  ttl;            // Time to live
	u_char  proto;          // Protocol
	u_short crc;            // Header checksum
	ip_address  saddr;      // Source address
	ip_address  daddr;      // Destination address
	u_int   op_pad;         // Option + Padding
};

/* UDP header*/
struct udp_header{
	u_short sport;          // Source port
	u_short dport;          // Destination port
	u_short len;            // Datagram length
	u_short crc;            // Checksum
};

union mac_addr
{
	u_char bytes[6];
	struct 
	{
		unsigned int d1;
		unsigned short d2;
	};
	struct 
	{
		unsigned int ip;
		unsigned short port;
	};
	bool operator == (const mac_addr& rhs) const
	{
		return d1==rhs.d1 && d2==rhs.d2;
	}
	bool operator < (const mac_addr& rhs) const
	{
		return (d1<rhs.d1) || ((d1==rhs.d1) && (d2<rhs.d2));
	}
	bool broadcast()
	{
		return d1==0xffffffff && d2==0xffff;
	}
};

struct ip_port_pair
{
	unsigned int ip;
	unsigned short port;
};

struct mac_header
{
	mac_addr daddr;
	mac_addr saddr;
	u_short type;
};

struct Packet
{
	mac_header	mac;
	ip_header	ip;
	udp_header	udp;
};


#pragma pack(pop)
